PHP反序列化漏洞(未完) |
您所在的位置:网站首页 › apache shiro rememberme反序列化 › PHP反序列化漏洞(未完) |
目录 类的结构 序列化作用 反序列化的作用 反序列化漏洞 魔术方法 类定义: 类是定义了一件事物的抽象特点(如猫是一个大类其中又细化品种),对象是具有类类型的变量,是对类的实例 内部构成:成员变量(属性)+成员函数(方法) 成员变量:定义在类内部的变量,该变量的值对外部是不可见的,但是可以通过成员函数访问,在类被实例化为对象后,该变量即可成为对象的属性。 成员函数:定义在类内部,可用于访问对象的数据。 继承:子类继承父类,类之间的关系 类的结构类:定义类名、成员变量、成员函数 序列化作用序列化是将对象的状态信息转换为可以存储或输出形式的过程 对象 ------序列化-------> 字符串 表达方式:空字符序列化表达方式,注意分号 数组序列化: a:3:{i:0;s:3:"noc";i:1;s:3:"asd";i:2;s:3:"zxc";} // a为数组 i:0代表noc 对象序列化: 不能序列化类,可以序列化对象,只能序列化成员变量不能序列化成员函数 O:4:"test":2:{s:3:"noc";s:4:"duck";s:2:"LL";s:4:"bird";} O:object,4:类名长度,test:类名,2:变量数量,s:3:变量名字长度,s:4:值的长度,duck:变量值 当将其改为私有属性后序列化变化: O:4:"test":2:{s:9:"testnoc";s:4:"duck";s:2:"LL";s:4:"bird";} //私有属性为了明确私有属性会在私有属性前加上类名,并且在序列化过程中加入二进制的00,url编码为%00,就是加了个空。 所以反序列化漏洞时常加urlencode()将其url编码查看 echo urlencode(serialize($a)) ; O%3A4%3A%22test%22%3A2%3A%7Bs%3A9%3A%22%00test%00noc%22%3Bs%3A4%3A%22duck%22%3Bs%3A2%3A%22LL%22%3Bs%3A4%3A%22bird%22%3B%7D 可以看到%00,所以是s:9 受保护的是前面加了星号(protected)并且星号前后也有00 O:4:"test":2:{s:6:"*noc";s:4:"duck";s:2:"LL";s:4:"bird";} O%3A4%3A%22test%22%3A2%3A%7Bs%3A6%3A%22%00%2A%00noc%22%3Bs%3A4%3A%22duck%22%3Bs%3A2%3A%22LL%22%3Bs%3A4%3A%22bird%22%3B%7D 对象里调用对象 生成一个对象但是对象里面的成员属性调用了另外一个对象 在$a实例化test1时调用另一个类test实例化后的对象 O:5:"test1":1:{s:3:"noc";O:4:"test":1:{s:2:"LL";s:4:"bird";}} //将黄色的部分序列化后赋值给了noc test1里就一个成员属性为noc,但这个成员属性对应的值是一个object对象,一个序列化被放在参数里来进行了提交(一个对象赋值给了成员属性,序列化对象里包含了一个序列化对象,不过这个序列化是赋值给了前面的成员属性的) 反序列化的作用将序列化后的参数还原成实例化对象 1、反序列化之后的内容为一个对象; 2、反序列化生成的对象里的值,由反序列化里的值提供;与原有类预定义的值无关; 3、反序列化不触发类的成员方法,需要调用方法后才能触发; 字符串 ------反序列化-------> 对象 输出被反序列化:输出仍然是一个对象(1、反序列化之后的内容为一个对象;) object(test)#1 (3) { ["LL"]=> string(4) "bird" ["noc":"test":private]=> string(4) "duck" ["XX":protected]=> string(5) "shack" } 当更改序列化里面的值,反序列化后的值也会变说白了,反序列化生成的对象和类是没有关系的(2、反序列化生成的对象里的值,由反序列化里的值提供;与原有类预定义的值无关;) 所以反序列化漏洞利用时根本不用考虑原来的值,这样就执行了我想执行的代码 object(test)#1 (3) { ["LL"]=> string(11) "birdsdwdasd" ["noc":"test":private]=> string(4) "duck" ["XX":protected]=> string(5) "shack" } 成员方法还是要从类上来 输出:fly (3、反序列化不触发类的成员方法,需要调用方法后才能触发;)
成因:反序列化过程中,unserialize()接受的值可控,通过更改这个值得到所需要的代码,就是生成对象的属性值 什么是反序列化漏洞:序列化和反序列化本身是为了实现数据在网络上完整高效的传输,但是由于反序列化过程中,对象的魔术方法会自动调用,魔术方法本身调用了别的方法,最终呈现一种链式调用,直到执行任意的代码或者命令。 尝试构造: 手动构造书写简单序列化字符串: 查看结果可行后调用animal: object(test)#1 (1) { ["LL"]=> string(17) "system("whoami");" } 由于windows没有正确编码有乱码,但确实执行了 问题:由于每次更改payload要更换关键字,如何不需要每次都更换 或如下提交: 一个预定义好的,在特定情况下触发的方法 魔术方法机制: 1、触发时机:动作不同触发的魔术方法也不同 2、功能 3、参数:一些特殊的魔术方法会传参 4、返回值 __construct():具有构造函数的类会在每次创建新对象时先调用此方法。 __destruct():析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。 __toString():方法用于一个类被当成字符串时应怎样回应。例如echo $obj;应该显示些什么。 此方法必须返回一个字符串,否则将发出一条 E_RECOVERABLE_ERROR 级别的致命错误。 __sleep():方法在一个对象被序列化之前调用; __wakeup():unserialize( )会检查是否存在一个_wakeup( )方法。如果存在,则会先调用_wakeup方法,预先准备对象需要的资源。 __call():在对象中调用一个不可以访问的方法时调用 __callStatic():用静态方式中调用一个不可以访问方法时调用 __get():获得一个类的成员变量时调用 __isset():当对不可访问属性调用isset()或empty()时调用 __set():设置一个类的成员变量时调用 __unset():当对不可访问属性调用unset()时被调用 __invoke():调用函数的方式调用一个对象时的回应方法 __set_state():调用var_export()导出类时,此静态方法被调用 __clone():当对象复制完成时调用 __autoload:尝试加载未定义的类 __debuginfo():打印所需调试信息 1、__construct() 很明显并没有触发后面的序列化与反序列化,只有实例化一个对象后会触发construct(相当于一个条件反应,没人会吃饭时候触发脱衣服吧) 所以只需要小小更改就可以调出计算器 2、__destruct() 首先判断析构函数会触发几次(触发了两次) 析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行 new的时候是不会触发的,但在销毁的时候会触发一次 反序列化时会触发 小小的更改一下还用上述计算器(没错会弹两次计算器) 或者两次whoami(也可以直接手动构造序列化字符串) 3、toString() 表达方式错误导致触发(常用于构造POP链接) 把对象被当成字符串时调用 把类test实体化并赋值给$a,此时$a是个对象,调用对象可以使用print_r或var_dump,如果使用echo或print只能以调用字符串的方式去调用对象,就是把对象当字符串使用,此时触发toString()
|
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |